package dao

import (
	"cld-quick-cli/database/keys"
	"cld-quick-cli/database/models"
	"cld-quick-cli/router/parameters"
	"cld-quick-cli/setup"
	"errors"
	"fmt"
	"github.com/C-RiceCongee/stitching/where"
	"github.com/go-redis/redis"
	"go.uber.org/zap"
)

// CheckPostExistByTitle 检查post是否已经存在！
func CheckPostExistByTitle(title string) error {
	var count int
	sql := "select count(post_id) from post where title = ?"
	err := setup.MysqlDB.Get(&count, sql, title)
	if err != nil {
		zap.L().Error(err.Error())
		return err
	}
	if count > 0 {
		zap.L().Error("帖子已经存在！")
		return errors.New("帖子已经存在！")
	}
	return nil
}

func InsertNewPost(postId int64, post *parameters.SendNewPostParams) error {
	sql := "insert into post (post_id,author_id,title, description,cover, content,  community_id,status) VALUES (?,?,?,?,?,?,?,?)"
	_, err := setup.MysqlDB.Exec(sql, postId, post.AuthorId, post.Title, post.Description, post.Cover, post.Content, post.CommunityId, post.Status)
	if err != nil {
		zap.L().Error(err.Error())
		return errors.New("帖子创建失败！")
	}
	return nil
}
func UpdateNewPost(post *parameters.UpdatePostParams) error {
	sql := "update post set title=?, description=?,cover=?, content=?, community_id=?,status=? where post_id = ?"
	_, err := setup.MysqlDB.Exec(sql, post.Title, post.Description, post.Cover, post.Content, post.CommunityId, post.Status, post.PostId)
	if err != nil {
		zap.L().Error(err.Error())
		return err
	}
	return nil
}

// GetPostDetailsById 获取帖子的详情！
func GetPostDetailsById(postId string) (*models.PostModel, error) {
	var post models.PostModel
	sql := "select post_id,community_id,title,description,cover,status,content,create_time,update_time from post where post_id = ?"
	err := setup.MysqlDB.Get(&post, sql, postId)
	if err != nil {
		zap.L().Error(err.Error())
		return nil, err
	}
	return &post, nil
}

// GetPostListByFilterParams 分页获取帖子 List!
func GetPostListByFilterParams(params *parameters.GetPostListByFilterParams) ([]models.PostDetailsModel, error) {
	posts := make([]models.PostDetailsModel, 0)
	// 反射组装 sql  函数！
	whereCDS, _, namedQueryMap, _ := where.ConnectWhereConditions[parameters.GetPostListByFilterParams](*params)
	namedQueryMap["offset"] = params.PageSize * (params.PageNumber - 1)
	namedQueryMap["limit"] = params.PageSize
	sql := fmt.Sprintf("select post_id,author_id,status,create_time,update_time,title,description,cover,community_id from post %s ORDER BY %s %s limit :limit offset :offset;", whereCDS, params.Sort, params.SortMode)
	rows, err := setup.MysqlDB.NamedQuery(sql, namedQueryMap)
	if err != nil {
		zap.L().Error(err.Error())
		return nil, err
	}
	for rows.Next() {
		var pdm models.PostDetailsModel
		err = rows.StructScan(&pdm)
		if err != nil {
			zap.L().Error(err.Error())
			return nil, err
		}
		community, err := GetCommunityDetailsByCommunityId(&pdm.PostModel.CommunityId)
		if err != nil {
			zap.L().Error(err.Error())
			return nil, err
		}
		pdm.CommunityModel = *community
		posts = append(posts, pdm)
	}
	return posts, nil
}

// GetPostListCountByFilterParams 获取帖子总数！
func GetPostListCountByFilterParams(params *parameters.GetPostListByFilterParams) (int64, error) {
	var count int64
	// 反射组装 sql  函数！
	_, sqlWhereSlice, _, nameQuerySlice := where.ConnectWhereConditions[parameters.GetPostListByFilterParams](*params)
	sql := fmt.Sprintf("select count(id) from post %s", sqlWhereSlice)
	err := setup.MysqlDB.Get(&count, sql, nameQuerySlice...)
	if err != nil {
		zap.L().Error(err.Error())
		return 0, err
	}
	return count, nil
}

// GetPostIdExistFromRedis 查询post是不是存在 （redis）
func GetPostIdExistFromRedis(postId string) (float64, error) {
	postTime, err := setup.RedisDB.ZScore(keys.KeyPostTimeZSet, postId).Result()
	if err != nil {
		zap.L().Error(err.Error())
		return 0, err
	}
	return postTime, nil
}

func UserVotePost(params *parameters.VotePostParams) error {
	// 1. 先取出帖子当前用户的投票状态 1 0 -1
	//keyPostVotedDynamic 拼接post-id的 zset key userid value user投票情况
	keyPostVotedDynamic := keys.KeyPostVotedDynamic + params.PostId
	userPostType, err := setup.RedisDB.ZScore(keyPostVotedDynamic, params.UserId).Result()
	// 报错 且不是 redis.nil
	if err != nil && err != redis.Nil {
		zap.L().Error(err.Error())
		return err
	}
	// 2. 把最新的用户投票状态插入redis!
	setup.RedisDB.ZAdd(keyPostVotedDynamic, redis.Z{
		Score:  float64(*params.Direction),
		Member: params.UserId,
	})
	// 3.计算差值 目标值 - 初始值！= differenceValue；计算分数 fraction * 432
	differenceValue := float64(*params.Direction) - userPostType
	fraction := differenceValue * 432
	// 4.获取当前帖子的分数 setList
	postScore, err := setup.RedisDB.ZScore(keys.KeyPostScoreZSet, params.PostId).Result()
	if err != nil && err != redis.Nil {
		zap.L().Error(err.Error())
		return err
	}
	calcScore := postScore + fraction
	_, err = setup.RedisDB.ZAdd(keys.KeyPostScoreZSet, redis.Z{
		Score:  calcScore,
		Member: params.PostId,
	}).Result()
	if err != nil && err != redis.Nil {
		zap.L().Error(err.Error())
		return err
	}
	return nil
}
